import glob from 'glob'
import Router from 'koa-router'
import { resolve } from 'path';
import R from 'ramda'
import _ from 'lodash'

const isArray=c=>_.isArray(c)?c:[c]
const routerMap=new Map()

const symbolPrefix=Symbol('prefix')
export class Route {
    constructor(app,apiPath){
        this.app=app
        this.apiPath=apiPath
        this.router=new Router()
    }
    init(){
        glob.sync(resolve(this.apiPath,'./**/*.js')).forEach(require)
        for(let [conf,controller] of routerMap){
          
            const controllers=isArray(controller)
            const prefixPath=conf.target[symbolPrefix]
          
            if(prefixPath)prefixPath=normalizePath(prefixPath)
            const routerPath=prefixPath+conf.path
            
            this.router[conf.method](routerPath,...controllers)
           
        }
        this.app.use(this.router.routes())
        this.app.use(this.router.allowedMethods())
    }
}
const normalizePath=path=>path.startsWith('/')?path:`/${path}`
const router=conf=>(target,key,descriptor)=>{
    conf.path=normalizePath(conf.path)
   
   
    routerMap.set({
        target: target,
        ...conf
      }, target[key])
}
export const controller=path=>target=>(target.prototype[symbolPrefix]=path)

export const get = path => router({
    method: 'get',
    path: path
  })
  
  export const post = path => router({
    method: 'post',
    path: path
  })
  
  export const put = path => router({
    method: 'put',
    path: path
  })
  
  export const del = path => router({
    method: 'delete',
    path: path
  })
  
  export const use = path => router({
    method: 'use',
    path: path
  })
  
  export const all = path => router({
    method: 'all',
    path: path
  })
  const decorate =(args,middleware)=>{
    let [target,key,descriptor]=args
    target[key]=isArray(target[key])
    target[key].unshift(middleware)
    return descriptor
  }
  const convert=middleware=>(...args)=>decorate(args,middleware)
  export const auth=convert(async (ctx,next)=>{
   // console.log('ctx.session.user')
    //console.log(ctx.session.user)
    if(!ctx.session.user){
      return (
        ctx.body={
          success:false,
          code:401,
          error:'登陆信息失效，重新登陆'
        }
      )
       
      
    }
    await next()
  })
  export const admin=roleExpected=>convert(async(ctx,next)=>{
    const {role}=ctx.session.user
   // console.log('admin session')
    //console.log(ctx.session.user)

    if(!role||role!=roleExpected){
      return (
        ctx.body={
          success:false,
          code:403,
          error:'你没有权限，来错地方了'
        }
      )
    }
    await next()
  })

  export const required=rules=>convert(async (ctx,next)=>{
    let errors=[]
    const checkRules=R.forEachObjIndexed(
      (value,key)=>{
        errors=R.filter(i=>!R.has(i,ctx,ctx.request[key]))(value)
      }
    )
    checkRules(rules)
    if(errors.length){
      ctx.body={
        success:false,
        code:412,
        error:`${errors.join(',')} is required`
      }
    }
    await next()
  })